iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
Software Development

From State Machine to XState系列 第 21

Day21 - 在 XState, 狀態機器裡無窮盡的狀態、 資料:Extended State and context - 1

  • 分享至 

  • xImage
  •  

1. Extended State

前面學習到的 FSM ,我們透過枚舉、列舉 (Enumerate),一個狀態機內所有可能的狀態,狀態機被提供的狀態是有限(Finite)的,所以叫我們稱之為有限狀態機 (Finite State Machine)。

但現實中的狀態機裡,我們可能會有些狀態是無限的、或是我們希望能帶某些資料(data)進去狀態機裡供其使用...
我們將這些無窮的狀態、資料稱之為 "Extended State"(擴充的狀態)。

比如說有一個水的狀態機,水可能會有「液態」、「固態」、「氣態」的三種狀態,但有時我們希望這組狀態機也能儲存當前水容量(amount)的資訊,這個水容量無法用 1,2,3... 列舉完,水量可能是無窮盡的。

在 XState 裡面的 Extended State 被稱作 "context"

我們繼續以底下這個狀態機為範例
https://ithelp.ithome.com.tw/upload/images/20210926/20130721htU67KKipL.png

我們要怎麼帶額外的資料進去狀態機內呢?
比如說這個門可能是屬於不同家店的,可能會有店名像是「綠洲酒吧」、「蘋果旗艦店」或是任何使用者輸入...,我們一時間無法列舉出所有可能...,但當我在判斷狀態轉換的防禦(Guard)、又或是執行 side effect 的 action 需要這個資料時,該怎麼辦?

2. Context

我們一樣可以把這個資料寫進去 machineConfig

  const doorMachine = createMachine(
    {
      // Machine identifier
      id: "door",
      // Initial context
+      context: {
+        shopName: "蘋果旗艦店"
+      },
      // Initial state
      initial: "關著",

      // State definitions
      states: {...}
    },  extraOptions)

接下來我們在回去看昨天的 Action

  {
    actions: {
      拉開大門: (c, e) =>
        console.error("side effect..........拉開厚重的門...."),
      關上大門: () => console.error("side effect..........推回厚重的門....")
    }
  }

有注意到『拉開大門』這個 side effect ,的 (c, e) 終於可以在今天一起介紹了,那個 c 就是 context(Extended State); e 就是 event (事件),也就是當我們在執行『拉開大門』時,我們可以拿到狀態機裡的資料及當下這個事件,我們可以直切印出 c,e 看看

  {
    actions: {
      拉開大門: (c, e) =>
-       console.error("side effect..........拉開厚重的門...."),
+       console.error(c, e, "side effect..........拉開厚重的門...."),
      關上大門: () => console.error("side effect..........推回厚重的門....")
    }
  }

https://ithelp.ithome.com.tw/upload/images/20211006/20130721CnQE7sQFBm.png

codesandbox DEMO

如此我們就能拿到這個被延伸、被狀態機記憶且共享的資料了

問題延伸

請問如何動態載入不同的 context ?

比如說我們這台狀態機想要給許多不同的店家共用,比如「綠洲酒吧」、「蘋果旗艦店」...

難道我需要一直寫一堆 appleStoreMachineConfig, oasisBarMachineConfig 卻只有 context 些微不一樣嗎?

請問我有辦法修改 context 的值嗎?

比如說今天我們「蘋果旗艦店」想要改店名成「蘋果尊絕不凡旗艦店」,我可以直接在狀態機裡面修改 context value 嗎?

這兩個問題將在明天一起被回答~

參考文獻

https://en.wikipedia.org/wiki/UML_state_machine
https://xstate.js.org/docs/guides/context.html#initial-context


上一篇
Day20 - 在 XState 與 Side Effect 互動吧~ action API
下一篇
Day22 - 在 XState, 狀態機器裡無窮盡的狀態、 資料:Extended State and context and assign API - 2
系列文
From State Machine to XState31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言